#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<locale.h>
#include<wchar.h>
#include<X11/X.h>
#include<X11/Xlib.h>
#include<GL/gl.h>
#include<GL/glx.h>
#include<GL/glu.h>
	
int
main(int argc, char *argv[])
{
	struct
	{
		GLXContext id;
		struct
		{
			XVisualInfo *info;
			GLint *attributes;
		} visual;
	} context;
	struct
	{
		Window id;
		XSetWindowAttributes attributes;
		struct
		{
			Atom delete;
		} protocols;
		XEvent event;
	} window;
	struct
	{
		Display *id;
		Window root;
		Colormap colormap;
		XWindowAttributes attributes;
	} display;
	int play = 1;

	if(!setlocale(LC_ALL, "en_US.UTF-8"))
		setlocale(LC_ALL, "");

	display.id = XOpenDisplay(NULL);
	display.root = DefaultRootWindow(display.id);
	XGetWindowAttributes(display.id, display.root, &display.attributes);
	context.visual.attributes = (GLint [5]){ GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
	context.visual.info = glXChooseVisual(display.id, 0, context.visual.attributes);
	display.colormap = XCreateColormap(display.id, display.root, context.visual.info->visual, AllocNone);
	window.attributes.colormap = display.colormap;
	window.attributes.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
	window.id = XCreateWindow(display.id, display.root, (display.attributes.width - 640) / 2, (display.attributes.height - 480) / 2, 640, 480, 0, context.visual.info->depth, InputOutput, context.visual.info->visual, CWColormap | CWEventMask, &window.attributes);
	window.protocols.delete = XInternAtom(display.id, "WM_DELETE_WINDOW", True);
	XSetWMProtocols(display.id, window.id, &window.protocols.delete, 1); 
	XMapWindow(display.id, window.id);
	XStoreName(display.id, window.id, "CodePorts!");
	context.id = glXCreateContext(display.id, context.visual.info, NULL, GL_TRUE);
	glXMakeCurrent(display.id, window.id, context.id);
	glEnable(GL_DEPTH_TEST); 
	while(play)
	{
		XNextEvent(display.id, &window.event);
		switch(window.event.type)
		{
			case Expose:
			{
				XWindowAttributes attributes;

				if(window.event.xexpose.count != 0) break;
				XGetWindowAttributes(display.id, window.id, &attributes);
				glViewport(0, 0, attributes.width, attributes.height);

				glClearColor(0.5, 0.0, 0.5, 0.0);
				glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

				glMatrixMode(GL_PROJECTION);
				glLoadIdentity();
				glOrtho(-1., 1., -1., 1., 1., 20.);

				glMatrixMode(GL_MODELVIEW);
				glLoadIdentity();
				gluLookAt(0., 0., 10., 0., 0., 0., 0., 1., 0.);

				glBegin(GL_QUADS);
				glColor3f(1., 0., 0.); glVertex3f(-.75, -.75, 0.);
				glColor3f(0., 1., 0.); glVertex3f( .75, -.75, 0.);
				glColor3f(0., 0., 1.); glVertex3f( .75,  .75, 0.);
				glColor3f(1., 1., 0.); glVertex3f(-.75,  .75, 0.);
				glEnd();

				glXSwapBuffers(display.id, window.id);
				break;
			}
			case KeyPress:
			case ButtonPress:
			{
				play = 0;
				break;
			}
			case ClientMessage:
			{
				if(strcmp(XGetAtomName(display.id, window.event.xclient.message_type), "WM_PROTOCOLS") == 0)
					play = 0;
				break;
			}
		}
	}
	glXMakeCurrent(display.id, None, NULL);
	glXDestroyContext(display.id, context.id);
	XDestroyWindow(display.id, window.id);
	XFree(context.visual.info);
	XCloseDisplay(display.id);
	return EXIT_SUCCESS;
}
